package com.redstar.interesting.common.starter.filter;

import com.redstar.interesting.common.constants.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * @author lihongxing
 */
@Component
public class WebTraceIDFilter extends OncePerRequestFilter implements Ordered {

    private static final Logger log = LoggerFactory.getLogger(WebTraceIDFilter.class);

    private static final String MSG = "Request blocked! cause:The parameter has SQL injection risks or contains invalid characters";

    public WebTraceIDFilter() {
        logger.info("WebTraceIDFilter初始化成功。。。");
    }

    @Override
    public int getOrder() {
        //最先执行
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 读取HTTP头 traceId
        String traceId = request.getHeader(Constants.TRACE_ID);
        if (!StringUtils.hasText(traceId)) {
            traceId = UUID.randomUUID().toString().replace("-", "");
        }
        // 塞到MDC上下文中
        MDC.put(Constants.TRACE_ID, traceId);
        long start = System.currentTimeMillis();
        log.info("接口请求开始>>>>>>:{}", request.getRequestURI());
        try {
            //包装请求防止特殊字符和SQL注入攻击
            BodyRequestWrapper wrapper = new BodyRequestWrapper(request);
            if (!wrapper.isPass()) {
                log.info("url = {}", request.getRequestURI());
                log.info(MSG);
                response.addHeader(Constants.TRACE_ID, MDC.get(Constants.TRACE_ID));
                response.addHeader("content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
                response.getWriter().write(MSG);
                return;
            }
            filterChain.doFilter(wrapper, response);
        } finally {
            log.info("接口请求结束>>>>>>:{},耗时:{}ms", request.getRequestURI(), System.currentTimeMillis() - start);
            MDC.clear();
        }
    }
}
